import importlib
import docker


class MyDocker(object):

    __version = "1.0"
    __docker_module_name = "docker"
    __docker_client = None
    __RUNING_STATUS = "running"
    __CREATED_STATUS = "created"
    __EXITED_STATUS = "exited"

    def __init__(self,base_url,version=None,time_out=None):

       """
            查看docker模块是否存在
       """
       docker_module = importlib.find_loader(self.__docker_module_name)

       if not docker_module:
           print("docker module in not exists,please install")
           exit()
       importlib.import_module(self.__docker_module_name)

       try:

        self.__docker_client = docker.DockerClient(base_url,version,time_out)

       except Exception as e:

        print("连接"+base_url+" docker error:"+e)

    #   已验证  列出所有镜像信息
    def images(self,showname=False):

        images = self.__docker_client.images.list()
        image_list = []

        for image in images:

            if not showname:
                temp_image_info = {}
                temp_image_info['short_id'] = image.short_id.replace("sha256:", "")
                temp_image_info['id'] = image.id.replace("sha256:", "")
                temp_image_info['tags'] = image.tags
                image_list.append(temp_image_info)
                del temp_image_info
            else:
                image_list.append(image.tags)
        return image_list

    #   已验证 拉取镜像
    def pull(self,image_name):

        if image_name.find(":") ==-1:
            image_name = image_name+":latest"
        return self.__docker_client.images.pull(image_name)

    #   已验证 可以查询镜像信息
    def search(self,image_name):

        return self.__docker_client.images.search(image_name)

    # **
    def tag(self,image_flag,repo,tag_name=None,**keyword):

        image = self.findImageById(image_flag)
        if image:
            return image.tag(repo,tag_name,**keyword)
        else:
            image = self.findImageByName(image_flag)
            if image.__len__()==0:
                raise Exception("image is not exists")
            return image[0].tag(repo, tag_name, **keyword)

    # 已验证
    def findImageById(self,id):
        image_lists = self.images()
        find_image = None
        for image in image_lists:
            if id == image['id'] or id == image['short_id']:
                find_image = image
                break
        if find_image == None:
            return find_image
        return self.__docker_client.images.get(find_image['id'])

    # 已验证
    def findImageByName(self,name):

        image_lists = self.images()

        find_image = []

        name = name.lower()

        for image in image_lists:

            for tag in image['tags']:

                if tag.find(name)!=-1:

                    find_image.append(image)

        if find_image.__len__() == 0:
            return None
        return [self.__docker_client.images.get(find_image[0]['id'])]

    #   已验证
    def rmi(self,flag):

        image_byid = self.findImageById(flag)

        if image_byid:
            self.__docker_client.images.remove(id=flag)
            return True
        else:
            images_byname = self.findImageByName(flag)

            if images_byname == None:
                raise Exception("image is not exists")
            self.__docker_client.images.remove(images_byname[0].id)
            return True

    #   已验证
    def ps(self,all=False):

        if all:

            return self.__docker_client.containers.list(all=True)

        else:

            return self.__docker_client.containers.list()

    #   已验证
    def create(self,image_flag,cmd,name=None,volumes={},ports={},i=False,t=False,d=True,**other_opts):

        image = self.findImageById(image_flag)
        if image:
            return self.__docker_client.containers.create(image.id,cmd,name=name,volumes=volumes,ports=ports,stdin_open=i,tty=t,detach=d,**other_opts)
        else:
            image = self.findImageByName(image_flag)
            if image:
                return self.__docker_client.containers.create(image[0].id,cmd,name=name,volumes=volumes,ports=ports,stdin_open=i,tty=t,detach=d,**other_opts)
            else:
                raise Exception("image is not exists")

    #   已验证
    def findContainerById(self,container_id):

        containers = self.ps(all=True)
        get_container = None
        for container in containers:
            if container.id == container_id:
                return container
        return get_container

    #   已验证
    def findContainerByName(self,container_name):

        containers = self.ps(all=True)
        get_container = None
        for container in containers:
            if container.name == container_name:
                return container
        return get_container

    #   已验证
    def stop(self,container_flag):

        container = self.findContainerById(container_flag)

        if container and container.status == self.__RUNING_STATUS:
            return container.stop()

        else:
            container = self.findContainerByName(container_flag)
            if container and container.status == self.__RUNING_STATUS:
                return container.stop()
            elif container.status == self.__CREATED_STATUS or container.status == self.__EXITED_STATUS:
                raise Exception("container is already stop status")
            else:
               self.__notExistsContainer()

    #   已验证
    def start(self,container_flag):
        container = self.findContainerById(container_flag)

        if container and container.status == self.__RUNING_STATUS:
            return container.stop()

        else:
            container = self.findContainerByName(container_flag)
            if container and container.status == self.__RUNING_STATUS:
                raise Exception("container is already runing status")
            elif container.status == self.__CREATED_STATUS or container.status == self.__EXITED_STATUS:
                container.start()
            else:
                self.__notExistsContainer()

    #   已验证
    def rm(self,container_flag):

        container = self.findContainerById(container_flag)
        if container:
            return container.remove(force=True)
        else:
            container = self.findContainerByName(container_flag)

            if container:
                return container.remove(force=True)
            else:
                self.__notExistsContainer()

    #   已验证
    def run(self,image_flag,cmd,name=None,volumes={},ports={},i=False,t=False,d=True,**other_opts):

        return self.__docker_client.containers.run(image_flag,cmd,name=name,volumes=volumes,ports=ports,stdin_open=i,tty=t,detach=d,**other_opts)

    #   **
    def exec(self,container_flag,shell_cmd,i=True,t=True):

        container = self.findContainerById(container_flag)
        if container:
            return container.exec_run(shell_cmd,stdin=i,tty=t)

    #   **
    def commit(self,container_flag,image_repo,image_tag,author="",message="",):

        container = self.findContainerById(container_flag)

        if container:


            if container.status == self.__RUNING_STATUS:
                commit_result = container.commit(image_repo,image_tag,message=message,author=author)
                return commit_result
            else:
                return container.commit(image_repo, image_tag, message=message, author=author)

        else:
            container = self.findContainerByName(container_flag)
            if container:
                if container.status == self.__RUNING_STATUS:
                    commit_result = container.commit(image_repo, image_tag, message=message, author=author)
                    return commit_result
                else:
                    return container.commit(image_repo, image_tag, message=message, author=author)
            else:
                self.__notExistsContainer()

    #   已验证
    def restart(self,container_flag):

        conatiner = self.findContainerById(container_flag)

        if conatiner:
           return conatiner.restart()
        else:
            conatiner = self.findContainerByName(container_flag)
            if conatiner:
                return conatiner.restart()
            self.__notExistsContainer()

    def build(self,path,tag):

        return self.__docker_client.images.build(path=path,tag=tag)

    #   已验证
    def rename(self,container_flag,newname):

        container = self.findContainerById(container_flag)

        if container:
            return container.rename(newname)
        else:
            container = self.findContainerByName(container_flag)
            if container:
                container.rename(newname)
            self.__notExistsContainer()
        
    def __notExistsImage(self):
        
        raise Exception("image is not exists")
    
    def __notExistsContainer(self):
        raise Exception("container is not exists")